import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.zip.CRC32;
import java.util.zip.GZIPInputStream;

public final class OnDemandFetcher extends FileRequester implements Runnable {
	private final Deque aClass19_1344;
	private final Deque aClass19_1358;
	private final Deque aClass19_1368;
	private final Deque aClass19_1370;
	private int anInt1332;
	public int anInt1349;
	private int[] anIntArray1348;
	private int[] animationIndices;
	private Client clientInstance;
	private int completedCount;
	private int completedSize;
	private final CRC32 crc32;
	private final int[][] crcs;
	private OnDemandData current;
	private int expectedSize;
	private int filesLoaded;
	private final byte[][] fileStatus;
	private final byte[] gzipInputBuffer;
	private InputStream inputStream;
	private final byte[] ioBuffer;
	private int loopCycle;
	private int[] mapIndices1;
	private int[] mapIndices2;
	private int[] mapIndices3;
	private int[] mapIndices4;
	private byte[] modelIndices;
	private final Queue zippedNodes;
	public int onDemandCycle;
	private long openSocketTime;
	private OutputStream outputStream;
	private final Deque requested;
	private boolean running;
	private Socket connection;
	public String status;
	private int totalFiles;
	private int uncompletedCount;
	private final int[][] versions;
	private boolean waiting;
	private int writeLoopCycle;

	private void checkReceived() {
		OnDemandData onDemandData;
		synchronized (aClass19_1370) {
			onDemandData = (OnDemandData) aClass19_1370.popFront();
		}
		while (onDemandData != null) {
			waiting = true;
			byte abyte0[] = null;
			if (clientInstance.cacheIndices[0] != null) {
				abyte0 = clientInstance.cacheIndices[onDemandData.dataType + 1]
				.get(onDemandData.ID);
			}
			//if (!crcMatches(versions[onDemandData.dataType][onDemandData.ID], crcs[onDemandData.dataType][onDemandData.ID], abyte0)) {
			//	abyte0 = null;
			//}
			synchronized (aClass19_1370) {
				if (abyte0 == null) {
					aClass19_1368.insertBack(onDemandData);
				} else {
					onDemandData.buffer = abyte0;
					synchronized (aClass19_1358) {
						aClass19_1358.insertBack(onDemandData);
					}
				}
				onDemandData = (OnDemandData) aClass19_1370.popFront();
			}
		}
	}

	private void closeRequest(OnDemandData onDemandData) {
		try {
			if (connection == null) {
				long l = System.currentTimeMillis();
				if (l - openSocketTime < 4000L) {
					return;
				}
				openSocketTime = l;
				connection = clientInstance.openSocket(43594 + Client.portOff);
				inputStream = connection.getInputStream();
				outputStream = connection.getOutputStream();
				outputStream.write(15);
				for (int j = 0; j < 8; j++) {
					inputStream.read();
				}
				loopCycle = 0;
			}
			ioBuffer[0] = (byte) onDemandData.dataType;
			ioBuffer[1] = (byte) (onDemandData.ID >> 8);
			ioBuffer[2] = (byte) onDemandData.ID;
			if (onDemandData.incomplete) {
				ioBuffer[3] = 2;
			} else if (!Client.loggedIn) {
				ioBuffer[3] = 1;
			} else {
				ioBuffer[3] = 0;
			}
			outputStream.write(ioBuffer, 0, 4);
			writeLoopCycle = 0;
			anInt1349 = -10000;
			return;
		} catch (IOException ioexception) {
		}
		try {
			connection.close();
		} catch (Exception e) {
		}
		connection = null;
		inputStream = null;
		outputStream = null;
		expectedSize = 0;
		anInt1349++;
	}

	@SuppressWarnings("unused")
	private boolean crcMatches(int i, int j, byte data[]) {
		if ((data == null) || (data.length < 2)) {
			return false;
		}
		int k = data.length - 2;
		int l = ((data[k] & 0xff) << 8) + (data[k + 1] & 0xff);
		crc32.reset();
		crc32.update(data, 0, k);
		int i1 = (int) crc32.getValue();
		return (l == i) && (i1 == j);
	}

	public void disable() {
		running = false;
	}

	public int getAnimCount() {
		return animationIndices.length;
	}

	public int getModelIndex(int i) {
		return modelIndices[i] & 0xff;
	}

	public OnDemandData getNextNode() {
		OnDemandData onDemandData;
		synchronized (aClass19_1358) {
			onDemandData = (OnDemandData) aClass19_1358.popFront();
		}
		if (onDemandData == null) {
			return null;
		}
		synchronized (zippedNodes) {
			onDemandData.unlinkSub();
		}
		if (onDemandData.buffer == null) {
			return onDemandData;
		}
		int i = 0;
		try {
			GZIPInputStream gzipinputstream = new GZIPInputStream(new ByteArrayInputStream(
			onDemandData.buffer));
			do {
				if (i == gzipInputBuffer.length) {
					throw new RuntimeException("buffer overflow!");
				}
				int k = gzipinputstream.read(gzipInputBuffer, i, gzipInputBuffer.length - i);
				if (k == -1) {
					break;
				}
				i += k;
			} while (true);
		} catch (IOException _ex) {
			throw new RuntimeException("error unzipping");
		}
		onDemandData.buffer = new byte[i];
		System.arraycopy(gzipInputBuffer, 0, onDemandData.buffer, 0, i);
		return onDemandData;
	}

	public int getNodeCount() {
		synchronized (zippedNodes) {
			return zippedNodes.getSize();
		}
	}

	public int getVersionCount(int j) {
		return versions[j].length;
	}

	private void handleFailed() {
		uncompletedCount = 0;
		completedCount = 0;
		for (OnDemandData onDemandData = (OnDemandData) requested.getFront(); onDemandData != null; onDemandData = (OnDemandData) requested
		.getNext()) {
			if (onDemandData.incomplete) {
				uncompletedCount++;
			} else {
				completedCount++;
			}
		}
		while (uncompletedCount < 10) {
			OnDemandData onDemandData_1 = (OnDemandData) aClass19_1368.popFront();
			if (onDemandData_1 == null) {
				break;
			}
			if (fileStatus[onDemandData_1.dataType][onDemandData_1.ID] != 0) {
				filesLoaded++;
			}
			fileStatus[onDemandData_1.dataType][onDemandData_1.ID] = 0;
			requested.insertBack(onDemandData_1);
			uncompletedCount++;
			closeRequest(onDemandData_1);
			waiting = true;
		}
	}

	@Override
	public void method548(int i) {
		method558(0, i);
	}

	public void method554(boolean flag) {
		int j = mapIndices1.length;
		for (int k = 0; k < j; k++) {
			if (flag || (mapIndices4[k] != 0)) {
				method563((byte) 2, 3, mapIndices3[k]);
				method563((byte) 2, 3, mapIndices2[k]);
			}
		}
	}

	public void method558(int i, int j) {
		if ((i < 0) || (i > versions.length) || (j < 0) || (j > versions[i].length)) {
			return;
		}
		if (versions[i][j] == 0) {
			return;
		}
		synchronized (zippedNodes) {
			for (OnDemandData onDemandData = (OnDemandData) zippedNodes.getFront(); onDemandData != null; onDemandData = (OnDemandData) zippedNodes
			.getNext()) {
				if ((onDemandData.dataType == i) && (onDemandData.ID == j)) {
					return;
				}
			}
			OnDemandData onDemandData_1 = new OnDemandData();
			onDemandData_1.dataType = i;
			onDemandData_1.ID = j;
			onDemandData_1.incomplete = true;
			synchronized (aClass19_1370) {
				aClass19_1370.insertBack(onDemandData_1);
			}
			zippedNodes.insertBack(onDemandData_1);
		}
	}

	public void method560(int i, int j) {
		if (clientInstance.cacheIndices[0] == null) {
			return;
		}
		if (versions[j][i] == 0) {
			return;
		}
		if (fileStatus[j][i] == 0) {
			return;
		}
		if (anInt1332 == 0) {
			return;
		}
		OnDemandData onDemandData = new OnDemandData();
		onDemandData.dataType = j;
		onDemandData.ID = i;
		onDemandData.incomplete = false;
		synchronized (aClass19_1344) {
			aClass19_1344.insertBack(onDemandData);
		}
	}

	public int method562(int i, int k, int l) {
		int i1 = (l << 8) + k;
		for (int j1 = 0; j1 < mapIndices1.length; j1++) {
			if (mapIndices1[j1] == i1) {
				if (i == 0) {
					return mapIndices2[j1];
				} else {
					return mapIndices3[j1];
				}
			}
		}
		return -1;
	}

	public void method563(byte byte0, int i, int j) {
		if (clientInstance.cacheIndices[0] == null) {
			return;
		}
		if (versions[i][j] == 0) {
			return;
		}
		@SuppressWarnings("unused")
		byte[] abyte0 = clientInstance.cacheIndices[i + 1].get(j);
		// if(crcMatches(versions[i][j], crcs[i][j], abyte0))
		// return;
		// fileStatus[i][j] = byte0;
		if (byte0 > anInt1332) {
			anInt1332 = byte0;
		}
		totalFiles++;
	}

	public boolean method564(int i) {
		for (int k = 0; k < mapIndices1.length; k++) {
			if (mapIndices3[k] == i) {
				return true;
			}
		}
		return false;
	}

	public void method566() {
		synchronized (aClass19_1344) {
			aClass19_1344.clear();
		}
	}

	private void loadExtras() {
		while ((uncompletedCount == 0) && (completedCount < 10)) {
			if (anInt1332 == 0) {
				break;
			}
			OnDemandData onDemandData;
			synchronized (aClass19_1344) {
				onDemandData = (OnDemandData) aClass19_1344.popFront();
			}
			while (onDemandData != null) {
				if (fileStatus[onDemandData.dataType][onDemandData.ID] != 0) {
					fileStatus[onDemandData.dataType][onDemandData.ID] = 0;
					requested.insertBack(onDemandData);
					closeRequest(onDemandData);
					waiting = true;
					if (filesLoaded < totalFiles) {
						filesLoaded++;
					}
					status = "Loading extra files - " + (filesLoaded * 100) / totalFiles + "%";
					completedCount++;
					if (completedCount == 10) {
						return;
					}
				}
				synchronized (aClass19_1344) {
					onDemandData = (OnDemandData) aClass19_1344.popFront();
				}
			}
			for (int j = 0; j < 4; j++) {
				byte data[] = fileStatus[j];
				int k = data.length;
				for (int l = 0; l < k; l++) {
					if (data[l] == anInt1332) {
						data[l] = 0;
						OnDemandData onDemandData_1 = new OnDemandData();
						onDemandData_1.dataType = j;
						onDemandData_1.ID = l;
						onDemandData_1.incomplete = false;
						requested.insertBack(onDemandData_1);
						closeRequest(onDemandData_1);
						waiting = true;
						if (filesLoaded < totalFiles) {
							filesLoaded++;
						}
						status = "Loading extra files - " + (filesLoaded * 100) / totalFiles + "%";
						completedCount++;
						if (completedCount == 10) {
							return;
						}
					}
				}
			}
			anInt1332--;
		}
	}

	public boolean method569(int i) {
		return anIntArray1348[i] == 1;
	}

	private void readData() {
		try {
			int j = inputStream.available();
			if ((expectedSize == 0) && (j >= 6)) {
				waiting = true;
				for (int k = 0; k < 6; k += inputStream.read(ioBuffer, k, 6 - k)) {
					;
				}
				int l = ioBuffer[0] & 0xff;
				int j1 = ((ioBuffer[1] & 0xff) << 8) + (ioBuffer[2] & 0xff);
				int l1 = ((ioBuffer[3] & 0xff) << 8) + (ioBuffer[4] & 0xff);
				int i2 = ioBuffer[5] & 0xff;
				current = null;
				for (OnDemandData onDemandData = (OnDemandData) requested.getFront(); onDemandData != null; onDemandData = (OnDemandData) requested
				.getNext()) {
					if ((onDemandData.dataType == l) && (onDemandData.ID == j1)) {
						current = onDemandData;
					}
					if (current != null) {
						onDemandData.loopCycle = 0;
					}
				}
				if (current != null) {
					loopCycle = 0;
					if (l1 == 0) {
						Signlink.reporterror("Rej: " + l + "," + j1);
						current.buffer = null;
						if (current.incomplete) {
							synchronized (aClass19_1358) {
								aClass19_1358.insertBack(current);
							}
						} else {
							current.unlink();
						}
						current = null;
					} else {
						if ((current.buffer == null) && (i2 == 0)) {
							current.buffer = new byte[l1];
						}
						if ((current.buffer == null) && (i2 != 0)) {
							throw new IOException("missing start of file");
						}
					}
				}
				completedSize = i2 * 500;
				expectedSize = 500;
				if (expectedSize > l1 - i2 * 500) {
					expectedSize = l1 - i2 * 500;
				}
			}
			if ((expectedSize > 0) && (j >= expectedSize)) {
				waiting = true;
				byte abyte0[] = ioBuffer;
				int i1 = 0;
				if (current != null) {
					abyte0 = current.buffer;
					i1 = completedSize;
				}
				for (int k1 = 0; k1 < expectedSize; k1 += inputStream.read(abyte0, k1 + i1,
				expectedSize - k1)) {
					;
				}
				if ((expectedSize + completedSize >= abyte0.length) && (current != null)) {
					if (clientInstance.cacheIndices[0] != null) {
						clientInstance.cacheIndices[current.dataType + 1].store(abyte0.length,
						abyte0, current.ID);
					}
					if (!current.incomplete && (current.dataType == 3)) {
						current.incomplete = true;
						current.dataType = 93;
					}
					if (current.incomplete) {
						synchronized (aClass19_1358) {
							aClass19_1358.insertBack(current);
						}
					} else {
						current.unlink();
					}
				}
				expectedSize = 0;
			}
		} catch (IOException ioexception) {
			try {
				connection.close();
			} catch (Exception _ex) {
			}
			connection = null;
			inputStream = null;
			outputStream = null;
			expectedSize = 0;
		}
	}

	public void run() {
		try {
			while (running) {
				onDemandCycle++;
				int i = 20;
				if ((anInt1332 == 0) && (clientInstance.cacheIndices[0] != null)) {
					i = 50;
				}
				try {
					Thread.sleep(i);
				} catch (Exception e) {
				}
				waiting = true;
				for (int j = 0; j < 100; j++) {
					if (!waiting) {
						break;
					}
					waiting = false;
					checkReceived();
					handleFailed();
					if ((uncompletedCount == 0) && (j >= 5)) {
						break;
					}
					loadExtras();
					if (inputStream != null) {
						readData();
					}
				}
				boolean flag = false;
				for (OnDemandData onDemandData = (OnDemandData) requested.getFront(); onDemandData != null; onDemandData = (OnDemandData) requested
				.getNext()) {
					if (onDemandData.incomplete) {
						flag = true;
						onDemandData.loopCycle++;
						if (onDemandData.loopCycle > 50) {
							onDemandData.loopCycle = 0;
							closeRequest(onDemandData);
						}
					}
				}
				if (!flag) {
					for (OnDemandData onDemandData_1 = (OnDemandData) requested.getFront(); onDemandData_1 != null; onDemandData_1 = (OnDemandData) requested
					.getNext()) {
						flag = true;
						onDemandData_1.loopCycle++;
						if (onDemandData_1.loopCycle > 50) {
							onDemandData_1.loopCycle = 0;
							closeRequest(onDemandData_1);
						}
					}
				}
				if (flag) {
					loopCycle++;
					if (loopCycle > 750) {
						try {
							connection.close();
						} catch (Exception _ex) {
						}
						connection = null;
						inputStream = null;
						outputStream = null;
						expectedSize = 0;
					}
				} else {
					loopCycle = 0;
					status = "";
				}
				if (Client.loggedIn && (connection != null) && (outputStream != null)
				&& ((anInt1332 > 0) || (clientInstance.cacheIndices[0] == null))) {
					writeLoopCycle++;
					if (writeLoopCycle > 500) {
						writeLoopCycle = 0;
						ioBuffer[0] = 0;
						ioBuffer[1] = 0;
						ioBuffer[2] = 0;
						ioBuffer[3] = 10;
						try {
							outputStream.write(ioBuffer, 0, 4);
						} catch (IOException _ex) {
							loopCycle = 5000;
						}
					}
				}
			}
		} catch (Exception exception) {
			Signlink.reporterror("od_ex " + exception.getMessage());
		}
	}

	public void start(Archive archive, Client client) {
		String versionNames[] = { "model_version", "anim_version", "midi_version", "map_version" };
		for (int i = 0; i < 4; i++) {
			byte versionData[] = archive.getFile(versionNames[i]);
			int j = versionData.length / 2;
			Packet buffer = new Packet(versionData);
			versions[i] = new int[j];
			fileStatus[i] = new byte[j];
			for (int l = 0; l < j; l++) {
				versions[i][l] = buffer.getUnsignedShort();
			}
		}
		String crcNames[] = { "model_crc", "anim_crc", "midi_crc", "map_crc" };
		for (int k = 0; k < 4; k++) {
			byte crcData[] = archive.getFile(crcNames[k]);
			int crcLen = crcData.length / 4;
			Packet buffer = new Packet(crcData);
			crcs[k] = new int[crcLen];
			for (int l1 = 0; l1 < crcLen; l1++) {
				crcs[k][l1] = buffer.getInt();
			}
		}
		byte data[] = archive.getFile("model_index");
		int version = versions[0].length;
		modelIndices = new byte[version];
		for (int i = 0; i < version; i++) {
			if (i < data.length) {
				modelIndices[i] = data[i];
			} else {
				modelIndices[i] = 0;
			}
		}
		data = archive.getFile("map_index");
		Packet mapData = new Packet(data);
		version = data.length / 7;
		mapIndices1 = new int[version];
		mapIndices2 = new int[version];
		mapIndices3 = new int[version];
		mapIndices4 = new int[version];
		for (int i2 = 0; i2 < version; i2++) {
			mapIndices1[i2] = mapData.getUnsignedShort();
			mapIndices2[i2] = mapData.getUnsignedShort();
			mapIndices3[i2] = mapData.getUnsignedShort();
			mapIndices4[i2] = mapData.getUnsignedByte();
		}
		data = archive.getFile("anim_index");
		mapData = new Packet(data);
		version = data.length / 2;
		animationIndices = new int[version];
		for (int j2 = 0; j2 < version; j2++) {
			animationIndices[j2] = mapData.getUnsignedShort();
		}
		data = archive.getFile("midi_index");
		mapData = new Packet(data);
		version = data.length;
		anIntArray1348 = new int[version];
		for (int k2 = 0; k2 < version; k2++) {
			anIntArray1348[k2] = mapData.getUnsignedByte();
		}
		clientInstance = client;
		running = true;
		clientInstance.startRunnable(this, 2);
	}

	public OnDemandFetcher() {
		requested = new Deque();
		status = "";
		crc32 = new CRC32();
		ioBuffer = new byte[500];
		fileStatus = new byte[4][];
		aClass19_1344 = new Deque();
		running = true;
		waiting = false;
		aClass19_1358 = new Deque();
		gzipInputBuffer = new byte[65000];
		zippedNodes = new Queue();
		versions = new int[4][];
		crcs = new int[4][];
		aClass19_1368 = new Deque();
		aClass19_1370 = new Deque();
	}
}
